package com.keyin.protocol;

import java.io.IOException;

import android.content.Context;
import android.util.Log;

import com.keyin.android.cache.Cache;
import com.keyin.android.net.Callback;
import com.keyin.android.net.Http;
import com.keyin.android.net.Param;
import com.keyin.android.util.Tools;

public class Protocol {

	private String url;
	private Param param;
	private Context context;
	private OnJsonProtocolResult onProtocolResult;

	private Http http;
	private Callback callback;

	private boolean cache = true;

	public Protocol(Context context, String url, 
			Param param, boolean cache) {
		this.param = param;
		this.context = context;
		this.cache = cache;
		this.url = url;
	}
	
	public Protocol(Context context, String url, Param param) {
		this(context, url, param, true);
	}

	public String getUrl() {
		return url;
	}

	public Param getParam() {
		if (this.param == null) {
			param = new Param();
		}
		return param;
	}

	public void startTrans(OnJsonProtocolResult onResult) {
		onProtocolResult = onResult;
		Object cache = Cache.get(getUrl() + getParam().toString());

		if (cache != null && this.cache) {
			onProtocolResult.onResult(cache);
			return;
		}

		callback = getCallback();
		http = new Http(callback);
		http.start();
	}

	protected Callback getCallback() {
		return new Callback() {
			private int reconnectCount;

			@Override
			public Context getContext() {
				return context;
			}

			@Override
			public Param getHeader() {
				return null;
			}

			@Override
			public byte[] getPostParam() {
				try {
					String param = getParam().toString();
					byte[] data = param.getBytes("utf-8");

					return data;
				} catch (Exception e) {
					onException(new Exception("Get post param error !"));
					return null;
				}
			}

			@Override
			public String getUrl() {
				return Protocol.this.getUrl();
			}

			@Override
			public void onException(Exception e) {
				Tools.printException(e);
				onProtocolResult.onException(e);
			}

			@Override
			public void onRecieve(byte[] d) {
				try {
					String json = new String(d, 0, d.length, "utf-8");

					JsonBean obj = JsonHelper.parse(json,
							onProtocolResult.getJsonBeanClass());
					onProtocolResult.onResult(obj);

					if (cache) {
						Cache.put(getUrl() + getParam().toString(), obj);
					}
				} catch (Exception e) {
					reconnectCount++;
					if (reconnectCount > 3) {
						onException(e);
						return;
					}
					http.start();
				}
			}
		};
	}

	public abstract static class OnJsonProtocolResult {

		private Class<?> jsonBeanClass;

		public OnJsonProtocolResult(Class<?> jsonBeanClass) {
			this.jsonBeanClass = jsonBeanClass;
		}

		public Class<?> getJsonBeanClass() {
			return jsonBeanClass;
		}

		public abstract void onException(Exception e);

		public abstract void onResult(Object o);
	}
}
